package com.example.tasks

import org.apache.poi.hssf.usermodel.HSSFWorkbook
import org.apache.poi.ss.usermodel.CellType
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.dom4j.DocumentHelper
import org.dom4j.io.OutputFormat
import org.dom4j.io.SAXReader
import org.dom4j.io.XMLWriter
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import kotlin.system.exitProcess

/**
 * 需要在excel前加一列KEY。
 */

/*const val rootDir = "F:\\"

const val destDir = "${rootDir}\\strings"*/
const val filePath = "/Users/zhengjianxin/Downloads/Soreal 6-1 strings_13L111.xlsx"
fun main(args: Array<String>) {

    parseExcel(filePath)

    exitProcess(0)
}

fun parseExcel(filePath: String) {
    val dir = File(File(filePath).parentFile, "strings")
    dir.mkdirs()

    Excel2Xml().parseAndWrite(filePath, dir.absolutePath/*args[0], args[1]*/)
//    exitProcess(0)
}

class Excel2Xml {

    private val dirMap = mapOf("En" to "values", "Cs" to "values-zh-rCN", "Ct" to "values-zh-rTW", "German" to "values-de", "French" to "values-fr", "Indonesian" to "values-in", "Italian" to "values-it", "Japanese" to "values-ja", "Korean" to "values-ko", "Portuguese" to "values-pt", "Russian" to "values-ru", "Spanish" to "values-es", "Hindi" to "values-hi")

    fun parseAndWrite(filePath: String, dir: String) {
        val excelData = readFromExcel(filePath)

        writeData2Xml(excelData, dir)

//        buildConfigJson(excelData, keyPrefix)
    }

    fun writeData2Xml(data: ArrayList<Array<String?>>?, libDir: String, append: Boolean = false) {
        if (data == null) return
        val languageArray: Array<String?> = data[0]
        val threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
        val countDownLatch = CountDownLatch(languageArray.size - 1)
        languageArray.forEachIndexed { index, it ->
            if (!it.isNullOrEmpty() && index > 0) {
                // "$libDir\\src\\main\\res\\${map[it]}\\strings.xml"
                println("index=$index, $it")
                val xmlFile = if (append) "$libDir${File.separator}${dirMap[it]}${File.separator}strings.xml" else "$libDir${File.separator}${dirMap[it]}.xml"

                threadPool.execute {
                    writeToXml(data, index, xmlFile, append)
                    countDownLatch.countDown()
//                    println("$xmlFile, index:$valueIndex, threadId:${Thread.currentThread().id}")
                }

            } else {
                countDownLatch.countDown()
            }
        }
        countDownLatch.await()
    }


    private fun writeToXml(data: ArrayList<Array<String?>>, index: Int, xmlPath: String, append: Boolean) {
        val xmlFile = File(xmlPath)
        val document = if (append) SAXReader().read(xmlFile) else DocumentHelper.createDocument()
        val rootElement = if (append) document.rootElement else document.addElement("resources")
        data.forEachIndexed { i, it ->
            try {
                it.getOrNull(0)?.trim()?.let { key ->
                    if (!key.isNullOrEmpty() && /*!write2Json(key, keyPrefix) &&*/ i > 0) {
                        val value = it[index]
                        if (!value.isNullOrEmpty()) {
                            println("key=$key,value=$value")
                            rootElement.addElement("string").addAttribute("name", key).addText(transforms(value))
                        }
                    }
                }
            } catch (e: Exception) {
                println("${e.message},read $index of array size ${it.size} ,data=${it.contentDeepToString()}")
            }

        }

        val xmlWriter = XMLWriter(BufferedOutputStream(FileOutputStream(xmlFile)), createPrettyPrint())
        xmlWriter.write(document)
        xmlWriter.close()/*println("thread:${Thread.currentThread().id},$xmlFile")*/

    }

    private fun createPrettyPrint(): OutputFormat {
        return OutputFormat().apply {
            setIndentSize(4)
            isNewlines = true
            isTrimText = true
            isPadText = true
            isXHTML = true
        }
    }

    fun readFromExcel(filePath: String): ArrayList<Array<String?>>? {
        val workBook = getWorkBook(filePath) ?: return null
        val excelData = ArrayList<Array<String?>>()
        workBook.sheetIterator().forEach { sheet ->
            /*if (sheet.sheetName.equals("Client"))*/ for (i in 0..sheet.physicalNumberOfRows) {
            val row = sheet.getRow(i) ?: continue
            val columns = row.physicalNumberOfCells - 1
            val rowData = arrayOfNulls<String>(columns + 1)
            for (j in 0..columns) {
                val cell = row.getCell(j)

                val value = when (cell?.cellType) {
                    CellType.STRING -> cell.richStringCellValue.toString()
                    else -> ""
                }
                rowData[j] = value
            }
            excelData.add(rowData)
        }
        }
        try {
            workBook.close()
        } catch (e: Exception) {
        }
        return excelData
    }

    private fun transforms(string: String): String {
        var result = string
        //iOS占位符替换，类型还需要再确认。可以检查出非英文%的问题
        if (string.contains("%@")) result = string.replace("%@", "%s")
        //处理单词中‘s加转义符的
        val indexOfs = result.indexOf("'s")
        if (indexOfs != -1) {
            result = "${result.substring(0, indexOfs)}\\${result.substring(indexOfs)}"
        }
        if (string.contains("&")) result = result.replace("&", "&amp;")
        //处理单词中...转义
        if (string.contains("…")) result = result.replace("…", "&#8230;")
        //处理单词中–转义
        if (string.contains("–")) result = result.replace("–", "&#8211;")

        if (string.contains("'")) result = result.replace("'", "\\'")
        if (string.contains(/**/"\"")) result = result.replace("\"", "\\\"")
//        if (string.contains('\'')) result = appendTransform(result)
        return result
    }


    private fun appendData2Xml(data: ArrayList<Array<String?>>, index: Int, xmlFile: String) {
        val saxReader = SAXReader()
        val rootElement = saxReader.read(File(xmlFile)).rootElement

        data.forEach {
            val key = it[0]
            val value = it[index]
            if (!key.isNullOrEmpty()) rootElement.addElement("string").addAttribute("name", key).addText(value)
            println("append:$key, $value")
        }

        val xmlWriter = XMLWriter(FileOutputStream(File(xmlFile)), createPrettyPrint())
        xmlWriter.write(rootElement)
    }

    private fun getWorkBook(path: String): Workbook? {
        return when (path.substring(path.lastIndexOf("."))) {
            ".xls", ".XLS" -> {
                HSSFWorkbook(File(path).inputStream())
            }

            ".xlsx", ".XLSX" -> {
                XSSFWorkbook(File(path)/*OPCPackage.open(path)*/)
            }

            else -> {
                null
            }
        }
    }


}
